package cn.tedu.reflection;

import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/*本类用于测试暴力反射*/
public class TestReflect2 {
    /*1.通过暴力反射获取与操作属性*/
    @Test
    public void getFie2() throws Exception {
        //获取字节码对象
        Class<Person> clazz = Person.class;
        //获取指定的私有属性,注意需要传入属性名,确认要获取哪个私有属性
        Field field = clazz.getDeclaredField("name");
        Field field2 = clazz.getDeclaredField("age");

        System.out.println(field);//直接打印获取到的属性对象
        System.out.println(field.getType());
        System.out.println(field.getType().getName());

        //4.设置属性的值
        //4.1需要指定到底给哪个对象的name属性设置一个什么值
        Object obj = clazz.newInstance();//触发无参构造创建对象
        Object person2 = clazz.newInstance();//触发无参构造创建对象
        //4.2暴力反射,需要设置私有资源可见权限
        field.setAccessible(true);
        field2.setAccessible(true);

        //4.3通过刚刚获取到的属性对象,给刚刚创建好的obj对象设置属性值,值是赵六
        //field就是我们刚刚获取的name属性
        //set(m,n)--m是给那个对象的name属性设置值,n是设置的具体值
        field.set(obj,"赵六");
        field2.set(obj,5);
        field.set(person2,"海绵宝宝");
        field2.set(person2,9);

        //4.4field.get(m),m代表的就是查看哪个对象的这个name属性的值
        System.out.println(field.get(obj));
        System.out.println(field.get(person2));
        System.out.println(field2.get(person2));
        System.out.println(field2.get(obj));
    }

    /*本类用于测试暴力反射*/
    @Test
    public void getFie3() throws Exception {
        Class<?> clazz = Person.class;//获取字节码对象
        Field field =clazz.getDeclaredField("addr");//获取addr属性对象
        field.setAccessible(true);//设置属性私有可见的权限
        Object p3  =clazz.newInstance();
        field.set(p3,"北京");
        System.out.println(field.get(p3));
    }

    /*通过暴力反射获取与操作私有方法*/
    @Test
    public void getFunction2() throws Exception {
        Class<?> clazz = new Person().getClass();
        //提供字节码对象获取私有方法
        /*getDeclaredMethod(m,x,y,z)
        * m:要获取方法的名字
        * x,y,z...可变参数,指的是目标方法的参数个数可以根据实际情况改变,0/1/2...个参数
        * x y z传入的是参数对应的类型,而且这个类型也必须是字节码队象
        * */
        Method save = clazz.getDeclaredMethod("save", int.class, String.class);

        Object p1 = clazz.newInstance();
        //执行私有方法之前,需要设置权限!!!私有可见!!!
        save.setAccessible(true);

        /*invoke(o,x,y,z...)表示通过反射技术执行方法
        o :要给哪个对象执行此方法
        x,y,z...可变参数,之前获取的方法参数类型是什么,此处就传对应个数与类型的值
        * */
        save.invoke(p1,666,"哈哈哈");
    }
    /*巩固练习--通过暴力反射获取与操作私有方法*/
    @Test
    public void getFunction3() throws Exception {
        Class<?> clazz = Person.class;
        Method update = clazz.getDeclaredMethod("update");
        Object p2 = clazz.newInstance();
        update.setAccessible(true);
        update.invoke(p2);
    }
}

